/* Copyright 2013-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.snaker.engine.core;

import cn.easyplatform.EntityNotFoundException;
import cn.easyplatform.contexts.Contexts;
import cn.easyplatform.entities.beans.bpm.BpmBean;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.type.EntityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snaker.engine.IProcessService;
import org.snaker.engine.SnakerException;
import org.snaker.engine.access.Page;
import org.snaker.engine.access.QueryFilter;
import org.snaker.engine.entity.Process;
import org.snaker.engine.helper.AssertHelper;
import org.snaker.engine.helper.DateHelper;
import org.snaker.engine.helper.StreamHelper;
import org.snaker.engine.helper.StringHelper;
import org.snaker.engine.model.ProcessModel;
import org.snaker.engine.parser.ModelParser;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;


/**
 * 流程定义业务类
 * 
 * @author yuqs
 * @version 1.0
 */
public class ProcessService extends AccessService implements IProcessService {
	private static final Logger log = LoggerFactory
			.getLogger(ProcessService.class);

	public void check(Process process, String idOrName) {
		AssertHelper.notNull(process, "指定的流程定义[id/name=" + idOrName + "]不存在");
		if (process.getState() != null && process.getState().intValue() == 0) {
			throw new IllegalArgumentException("指定的流程定义[id/name=" + idOrName
					+ ",version=" + process.getVersion() + "]为非活动状态");
		}
	}

	/**
	 * 保存process实体对象
	 */
	public void saveProcess(Process process) {
		access().saveProcess(process);
	}

	/**
	 * 更新process的类别
	 */
	public void updateType(String id, String type) {
	}

	/**
	 * 根据id获取process对象 先通过cache获取，如果返回空，就从数据库读取并put
	 */
	public Process getProcessById(String id) {
		AssertHelper.notEmpty(id);
		CommandContext cc = Contexts.getCommandContext();
		BpmBean bb = cc.getEntity(id);
		if (bb == null)
			throw new EntityNotFoundException(EntityType.BPM.getName(), id);
		ProcessModel model = null;
		if (bb.getProcessModel() == null) {
			try {
				model = ModelParser.parse(bb.getContent().getBytes("utf-8"));
			} catch (UnsupportedEncodingException e) {
			}
			bb.setProcessModel(model);
		} else
			model = (ProcessModel) bb.getProcessModel();
		Process entity = new Process();
		entity.setDisplayName(bb.getDescription());
		entity.setName(bb.getName());
		entity.setId(id);
		entity.setModel(model);
		entity.setState(STATE_ACTIVE);
		return entity;
	}

	/**
	 * 根据流程定义xml的输入流解析为字节数组，保存至数据库中，并且put到缓存中
	 * 
	 * @param input
	 */
	public String deploy(InputStream input) {
		return deploy(input, null);
	}

	/**
	 * 根据流程定义xml的输入流解析为字节数组，保存至数据库中，并且put到缓存中
	 * 
	 * @param input
	 * @param creator
	 */
	public String deploy(InputStream input, String creator) {
		AssertHelper.notNull(input);
		try {
			byte[] bytes = StreamHelper.readBytes(input);
			ProcessModel model = ModelParser.parse(bytes);
			Integer version = access().getLatestProcessVersion(model.getName());
			Process entity = new Process();
			entity.setId(StringHelper.getPrimaryKey());
			if (version == null || version < 0) {
				entity.setVersion(0);
			} else {
				entity.setVersion(version + 1);
			}
			entity.setState(STATE_ACTIVE);
			entity.setModel(model);
			entity.setBytes(bytes);
			entity.setCreateTime(DateHelper.getTime());
			entity.setCreator(creator);
			saveProcess(entity);
			return entity.getId();
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
			throw new SnakerException(e.getMessage(), e.getCause());
		}
	}

	/**
	 * 根据流程定义id、xml的输入流解析为字节数组，保存至数据库中，并且重新put到缓存中
	 * 
	 * @param input
	 */
	public void redeploy(String id, InputStream input) {
		AssertHelper.notNull(input);
		Process entity = access().getProcess(id);
		AssertHelper.notNull(entity);
		try {
			byte[] bytes = StreamHelper.readBytes(input);
			ProcessModel model = ModelParser.parse(bytes);
			entity.setModel(model);
			entity.setBytes(bytes);
			access().updateProcess(entity);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
			throw new SnakerException(e.getMessage(), e.getCause());
		}
	}

	/**
	 * 根据processId卸载流程
	 */
	public void undeploy(String id) {
		Process entity = access().getProcess(id);
		entity.setState(STATE_FINISH);
		access().updateProcess(entity);
	}

	/**
	 * 级联删除指定流程定义的所有数据
	 */
	public void cascadeRemove(String id) {

	}

	/**
	 * 查询流程定义
	 */
	public List<Process> getProcesss(QueryFilter filter) {
		if (filter == null)
			filter = new QueryFilter();
		return access().getProcesss(null, filter);
	}

	/**
	 * 分页查询流程定义
	 */
	public List<Process> getProcesss(Page<Process> page, QueryFilter filter) {
		AssertHelper.notNull(filter);
		return access().getProcesss(page, filter);
	}
}
